<script setup lang="ts">
import RoomStatus from './components/RoomStatus.vue'
import RoomAction from './components/RoomAction.vue'
import RoomMessage from './components/RoomMessage.vue'

import { getOrderDetailAPI } from '@/services'
// 引入包
import io, { Socket } from 'socket.io-client'
// 引入服务器地址
import { baseURL } from '@/utils/request'
import { onMounted, onUnmounted, ref } from 'vue'
// 引入仓库
import { useUserStore } from '@/stores'
const store = useUserStore()
// 引入路由
import { useRoute } from 'vue-router'
import type { TimeMessages, Message } from '@/types/room'
import type { ConsultOrderItem, Image } from '@/types/consult'
import { MsgType, OrderType } from '@/enum'
import { nextTick } from 'vue'
import dayjs from 'dayjs'
import { provide } from 'vue'
import { showToast } from 'vant'
const route = useRoute()

// 定义数据
const consult = ref<ConsultOrderItem>()
// 调用接口获取数据
const getOrderDetail = async () => {
  const res = await getOrderDetailAPI(route.query.orderId as string)
  consult.value = res.data
}

// 默认消息数组
let list = ref<Message[]>([])

let socket: Socket
// 获取当前时间的字符串，，，dayjs库方法
const currentTime = ref(dayjs().format('YYYY-MM-DD HH:mm:ss'))
// 开关，避免刷新时页面也滚到最新数据
let isFirst = true

// 把提交评价需要的医生的ID和订单ID传给孙组件(evaluateCard)
provide('consult', consult)

// 修改评价状态的方法
const completeEva = (score: number) => {
  // 查找评价消息
  const item = list.value.find((item) => item.msgType === MsgType.CardEvaForm)
  if (item) {
    // 类型守卫，表示找到了评价消息
    item.msg.evaluateDoc = { score }
    // 修改当前消息的转态，改为已评价3

    item.msgType = MsgType.CardEva
  }
}
// 把修改评价状态的方法传给孙组件
provide('completeEva', completeEva)

onMounted(() => {
  // 初始化数据
  getOrderDetail()

  // 链接优医问诊服务器
  socket = io(baseURL, {
    auth: {
      token: `Bearer ${store.user?.token}`
    },
    query: {
      orderId: route.query.orderId
    }
  })
  // 监听连接
  socket.on('connect', function () {
    console.log('连接成功')
  })

  // 获取默认消息
  socket.on('chatMsgList', async ({ data }: { data: TimeMessages[] }) => {
    // console.log(data, 'data')
    const arr: Message[] = []
    data.forEach((item, i) => {
      if (i === 0) {
        // 记录第一项的时间，目的是在下拉刷新时 获取当前第一项时间之前的消息内容
        currentTime.value = item.createTime
      }

      // 每一个消息分组的第一条消息 系统消息
      arr.push({
        id: item.createTime,
        msgType: MsgType.Notify,
        createTime: item.createTime,
        msg: {
          content: item.createTime
        }
      })
      // 追加消息分组中的消息
      arr.push(...item.items)
    })
    // 在获取完数据之后再关闭loading效果
    refreshLoading.value = false
    // 通过判断data的长度，来查看还有没有历史消息记录
    if (data.length === 0) {
      return showToast('没有更多数据了')
    }
    list.value.unshift(...arr)
    // console.log(list.value, 'list')
    await nextTick()
    // dom加载异步操作，等待dom加载完，如果是第一次数据就滚动到最底部
    if (isFirst) {
      // 把未读消息全部变为已读，获取最后一个消息的ID,进入聊天室，所有消息就变为已读
      socket.emit('updateMsgStatus', arr[arr.length - 1].id)

      isFirst = false
      setTimeout(() => {
        window.scrollTo(0, document.body.scrollHeight)
      }, 500)
    }
  })

  // 接收消息
  socket.on('receiveChatMsg', async (event) => {
    // 往消息列表某位添加消息
    list.value.push(event)
    // 收到一条消息就已读一条
    socket.emit('updateMsgStatus', event.id)
    // 让页面滑动到最低下，能看到最新的消息，但是要等到dom更新完成
    await nextTick()

    // 监听一个load事件，等图片加载完在滚动  TODO---
    window.scrollTo(0, document.body.scrollHeight)
  })

  // 监听错误
  socket.on('err', (err) => {
    console.log(err)
  })

  // 监听断开链接
  socket.on('disconnect', function () {
    console.log('链接断开')
  })

  // 监听订单状态变化  ,一旦状态发生了变化，就重新获取订单数据
  socket.on('statusChange', getOrderDetail)
})

onUnmounted(() => {
  socket.close()
})

// 处理接收到子组件传过来的事件
const handelSendText = (msg: string) => {
  // 发送消息
  socket.emit('sendChatMsg', {
    // 发送方
    from: store.user?.id,
    // 接收方
    to: consult.value?.docInfo?.id,
    // 消息类型
    msgType: MsgType.MsgText,
    // 消息内容
    msg: {
      content: msg
    }
  })
}

// 处理接收到子组件传过来的事件
const handelSendImag = (img: Image) => {
  // 发送消息
  socket.emit('sendChatMsg', {
    // 发送方
    from: store.user?.id,
    // 接收方
    to: consult.value?.docInfo?.id,
    // 消息类型
    msgType: MsgType.MsgImage,
    // 消息内容
    msg: {
      picture: img
    }
  })
}

const refreshLoading = ref(false)
// 下拉刷新
const onRefresh = () => {
  // 下拉刷新i，组件内部把loading效果置为true，需要手动置为false
  // 需要四个参数：事件名，pageSize: number, lastTime: string, orderId: string
  socket.emit('getChatMsgList', 20, currentTime.value, route.query.orderId)

  // console.log('刷新了')
}
</script>

<template>
  <div class="room-page">
    <cp-nav-bar title="问诊室" />
    <!-- 状态 -->
    <room-status
      :status="consult?.status"
      :count-down="consult?.countdown"
    ></room-status>
    <!-- 聊天消息 -->
    <van-pull-refresh v-model="refreshLoading" @refresh="onRefresh">
      <room-message
        v-for="item in list"
        :key="item.id"
        :item="item"
      ></room-message>
    </van-pull-refresh>
    <!-- 操作栏 -->
    <room-action
      @send-text="handelSendText"
      @send-imag="handelSendImag"
      :disable="consult?.status !== OrderType.ConsultChat"
    ></room-action>
  </div>
</template>

<style lang="scss" scoped>
.room-page {
  // padding-top: 90px;
  padding-bottom: 60px;
  min-height: 100vh;
  box-sizing: border-box;
  background-color: var(--cp-bg);
  .van-pull-refresh {
    width: 100%;
    min-height: calc(100vh - 150px);
  }
}
</style>
